package com.ciaojian.client.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ciaojian.client.service.UserLoginServiceImpl;
import com.ciaojian.client.service.UserServiceImpl;
import com.ciaojian.client.util.WechatDecryptDataUtil;
import com.ciaojian.core.factory.ObjectMapperFactory;
import com.ciaojian.core.mapper.*;
import com.ciaojian.core.model.*;
import com.ciaojian.core.model.dto.WeChatUserDto;
import com.ciaojian.core.model.dy.DyOrder;
import com.ciaojian.core.util.*;
import com.ciaojian.miniapp.api.WxMiniAppApi;
import com.ciaojian.miniapp.model.request.Code2Session;
import com.ciaojian.miniapp.model.response.Code2SessionResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author Atlakyn
 */
@Slf4j
@Api(tags = "用户模块: 用户登录")
@RequestMapping("/login")
@RestController
public class UserLoginController {
    @Resource
    private UserLoginServiceImpl userLoginService;
    @Resource
    private UserServiceImpl userService;
    @Resource
    private UserMapper userMapper;
    @Resource
    private DyOrderMapper dyOrderMapper;
    @Resource
    private CouponCodeMapper couponCodeMapper;
    @Resource
    private CouponCodeTakeRecordMapper couponCodeTakeRecordMapper;

    @Value("${wxpay.appId}")
    private String appid;
    @Value("${wxpay.key}")
    private String secret;

    @ApiModelProperty("获取用户手机号")
    @PostMapping("/decode")
    public Result decode(@RequestBody WeChatUserDto weChatUserDto, HttpServletRequest request) throws JsonProcessingException {
        // 通过code跟微信获取信息
        Code2Session code2Session = Code2Session.builder()
                .appid(appid)
                .secret(secret)
                .js_code(weChatUserDto.getCode())
                .build();
        Code2SessionResponse response = WxMiniAppApi.code2Session(code2Session, Code2SessionResponse.class);

        weChatUserDto.setSessionKey(response.getSession_key());


        String userInfo = WeChatUtil.decryptData(weChatUserDto.getEncryptedData(), response.getSession_key(), weChatUserDto.getIv());
        Assert.hasText(userInfo, "用户信息错误");

        ObjectMapper om = ObjectMapperFactory.getObjectMapperInstance();
        weChatUserDto.setUserInfo(om.readValue(userInfo, Map.class));
        return Result.ok(weChatUserDto);
    }

    @ApiOperation("刷新用户的 UnionId")
    @GetMapping("/updateUnionId")
    public Result updateUnionId(Integer userId, String unionId, String openId) {
        Assert.notNull(userId, "userId 不能为空");
        User user = new User().selectById(userId);
        if (user == null) {
            return Result.ok();
        }
        user.setUnionid(unionId);
        user.setOpenid(openId);
        user.updateById();
        return Result.ok();
    }

    /**
     * 通过code获取openid
     */
    @ApiOperation("获取 openid")
    @GetMapping("/userOpenId")
    public Result userOpenId(@ApiParam("客户端获取的code") String code) {
        Assert.hasText(code, "code不能为空");
        Assert.hasText(code, "encryptedData不能为空");
        Assert.hasText(code, "iv不能为空");
        try {
            Code2Session code2Session = Code2Session.builder()
                    .appid(appid)
                    .secret(secret)
                    .js_code(code)
                    .build();
            Code2SessionResponse response = WxMiniAppApi.code2Session(code2Session, Code2SessionResponse.class);
            return Result.ok(response);
        } catch (Exception e) {
            log.error(e.toString());
            return Result.error("系统异常");
        }
    }

    /**
     * 微信用户授权，把用户信息保存，并且登录
     */
    @PostMapping
    public Result login(String nickName, String avatarUrl, String openid, String unionId, Integer invitedId) {
//        Assert.hasText(nickName, "昵称不能为空");
//        Assert.hasText(avatarUrl, "头像不能为空");
        Assert.hasText(openid, "openid不能为空");
        Assert.hasText(unionId, "unionId不能为空");
        try {
            User user = userLoginService.getUserByUnionId(unionId);
            String token = TokenUtil.makeToken(openid);
            HashMap<String, Object> map = new HashMap<>(2);
            map.put("token", token);
            User data = new User();
            User newUser;
            // 新用户
            if (user == null) {
                if (nickName != null){
                    data.setNickName(nickName);
                }
                if (avatarUrl != null) {
                    data.setAvatarUrl(avatarUrl);
                }
                data.setAddTime(new Date());
                data.setOpenid(openid);
                data.setUnionid(unionId);
                userLoginService.insert(data);
                newUser = userLoginService.getUserByUnionId(unionId);
                userService.invited(invitedId, newUser.getId());
            } else {
                user.setOpenid(openid);
                if (nickName != null){
                    user.setNickName(nickName);
                }
                if (avatarUrl != null) {
                    user.setAvatarUrl(avatarUrl);
                }
                user.setUnionid(unionId);
                user.updateById();
                userLoginService.updateUserByUnionId(user);
                newUser = userLoginService.getUserByUnionId(unionId);

            }
            map.put("user", newUser);
            map.put("userLoginInfo", userLoginService.loginSuccess(newUser.getId()));
            return Result.ok(map);
        } catch (Exception e) {
            log.error(e.toString());
            return Result.error("系统异常");
        }
    }


    /**
     * 获取手机号
     *
     * @param session_key
     * @param encrypteData
     * @param iv
     * @return
     */
    @GetMapping("/getPhoneNew")
    public Result getPhone(String session_key, String encrypteData, String iv) {
        try {
            if (encrypteData == null || "".equals(encrypteData)) {
                return Result.error("encrypteData不能为空");
            }
            if (encrypteData == null || "".equals(encrypteData)) {
                return Result.error("encrypteData不能为空");
            }
            if (iv == null || "".equals(iv)) {
                return Result.error("iv不能为空");
            }
            if (session_key == null || "".equals(session_key)) {
                return Result.error("session_key不能为空");
            }
            WechatDecryptDataUtil wechatDecryptDataUtil = new WechatDecryptDataUtil(session_key);
            System.out.println("wechatDecryptDataUtil=====" + wechatDecryptDataUtil);
            JSONObject jsonObject = wechatDecryptDataUtil.decryptData(encrypteData, iv);
            return Result.ok(jsonObject);
        } catch (Exception e) {
            log.error(e.toString());
            return Result.error("系统异常");
        }
    }

    /**
     * 保存用户  并且登录 (新)
     */
    @PostMapping("/setPhoneNew")
    public Result setPhone(@RequestBody String info) {
        JSONObject jsonObject = JSON.parseObject(info);
//            Integer userId = jsonObject.getInteger("userId");
        String telphone = jsonObject.getString("phoneNumber");

        String openid = jsonObject.getString("openid");
        String unionId = jsonObject.getString("unionId");
        Integer invitedId = jsonObject.getInteger("invitedId");

        try {
//            if (userId == null || "".equals(userId)) {
//                return Result.error("用户ID不能为空");
//            }
            if (telphone == null || "".equals(telphone)) {
                return Result.error("手机号不能为空");
            }
            if (openid == null || "".equals(openid)) {
                return Result.error("openid不能为空");
            }

            String token = TokenUtil.makeToken(openid);
            HashMap<String, Object> map = new HashMap<>(2);
            map.put("token", token);
            User user;
            User userWx;
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("telphone", telphone);
            user = userMapper.selectOne(userQueryWrapper);
            //  通过手机号找
            if (ObjectUtil.isNotNull(user)){
                user.setWx(true);
                user.setUpdateTime(new Date());
                user.setOpenid(openid);
                user.setUnionid(unionId);
                user.setTelphone(telphone);
                if (ObjectUtil.isNull(user.getAddTime())) {
                    user.setAddTime(new Date());
                }
                try {
                     userMapper.updateById(user);

                    map.put("user", user);
                    map.put("userLoginInfo", userLoginService.loginSuccess(user.getId()));
                    return Result.ok(map);
                }catch (Exception e){
                    insertUserError(openid,"重复:"+e.getMessage(),user.getId(),telphone,1);

                    QueryWrapper<User> userqw = new QueryWrapper<>();
                    userqw.eq("openid", openid);
                    userWx = userMapper.selectOne(userqw);
                    userWx.setWx(true);
                    userWx.setUpdateTime(new Date());
                    userWx.setOpenid(openid);
                    userWx.setUnionid(unionId);
                    userWx.setTelphone(telphone);
                    userWx.setDy(true);
                    userWx.setDyNickName(user.getDyNickName());
                    userWx.setDyAvatarUrl(user.getDyAvatarUrl());
                    userWx.setDyOpenid(user.getDyOpenid());
                    userWx.setDyUnionid(user.getDyUnionid());
                    userWx.setAddTime(user.getDyAddTime());
                    boolean b = user.deleteById();
                    if (b) {
                        userWx.updateById();

                        QueryWrapper<DyOrder> dyOrderQueryWrapper = new QueryWrapper<>();
                        dyOrderQueryWrapper.eq("user_id", user.getId());
                        List<DyOrder> dyOrders = dyOrderMapper.selectList(dyOrderQueryWrapper);
                        for (DyOrder dyOrder : dyOrders) {
                            dyOrder.setUserId(userWx.getId());
                            dyOrder.updateById();
                        }

                        QueryWrapper<CouponCode> couponCodeQueryWrapper = new QueryWrapper<>();
                        couponCodeQueryWrapper.eq("user_id", user.getId());
                        List<CouponCode> couponCodes = couponCodeMapper.selectList(couponCodeQueryWrapper);
                        for (CouponCode couponCode : couponCodes) {
                            couponCode.setUserId(userWx.getId());
                            couponCode.updateById();
                        }

                        QueryWrapper<CouponCodeTakeRecord> couponCodeTakeRecordQueryWrapper = new QueryWrapper<>();
                        couponCodeTakeRecordQueryWrapper.eq("user_id", user.getId());
                        List<CouponCodeTakeRecord> couponCodeTakeRecords = couponCodeTakeRecordMapper.selectList(couponCodeTakeRecordQueryWrapper);
                        for (CouponCodeTakeRecord couponCodeTakeRecord : couponCodeTakeRecords) {
                            couponCodeTakeRecord.setUserId(userWx.getId());
                            couponCodeTakeRecord.updateById();
                        }
                    }
                    map.put("user", userWx);
                    map.put("userLoginInfo", userLoginService.loginSuccess(userWx.getId()));
                    return Result.ok(map);
                }
            }else {
                try {
                    QueryWrapper<User> userqw = new QueryWrapper<>();
                    userqw.eq("openid", openid);
                    user = userMapper.selectOne(userqw);
                    if (ObjectUtil.isNotNull(user)) {
                        if (ObjectUtil.isNull(user.getAddTime())) {
                            user.setAddTime(new Date());
                        }
                        user.setWx(true);
                        user.setUpdateTime(new Date());
                        user.setOpenid(openid);
                        user.setUnionid(unionId);
                        user.setTelphone(telphone);
                        userMapper.updateById(user);
                        map.put("user", user);
                        map.put("userLoginInfo", userLoginService.loginSuccess(user.getId()));
                        return Result.ok(map);

                    } else {
                        user = new User();
                        user.setTelphone(telphone);
                        user.setWx(true);
                        user.setUpdateTime(new Date());
                        user.setAddTime(new Date());
                        user.setOpenid(openid);
                        user.setUnionid(unionId);

                        Integer id = userMapper.maxId();
                        id++;
                        user.setId(id);
                        try {
                            userMapper.insert(user);
                        }catch (Exception e){
                            id = id+3;
                            user.setId(id);
                            userMapper.insert(user);
                        }

                        userQueryWrapper.eq("telphone", telphone);
                        User newUser = userMapper.selectOne(userQueryWrapper);
                        userService.invited(invitedId, newUser.getId());
                        map.put("user", newUser);
                        map.put("userLoginInfo", userLoginService.loginSuccess(newUser.getId()));
                        return Result.ok(map);
                    }
                }catch (Exception e){
                    if (ObjectUtil.isNotNull(user.getId())) {
                        insertUserError(openid, e.getMessage(), user.getId(), telphone,2);
                    }else {
                        insertUserError(openid, e.getMessage(), null, telphone,3);
                    }
                    return Result.error("系统异常");
                }
            }
        } catch (Exception e) {
            return Result.error("系统异常");
        }
    }
    /**
     * 错误登录用户写入
     */
    public void insertUserError(String openid, String message, Integer id, String telphone,Integer errortype){
        UserError userError = new UserError();
        userError.setOpenid(openid);
        userError.setDate(new Date());
        userError.setMsg(message);
        userError.setType("微信");
        userError.setUserId(id);
        userError.setTelphone(telphone);
        userError.setErrortype(errortype);
        userError.insert();
    }



    /**
     * 微信用户授权，把用户信息保存，
     */
    @PostMapping("/saveUserInfo")
    public Result saveUserInfo(@RequestBody String info) {
        try {

            JSONObject jsonObject = JSON.parseObject(info);
//            Integer userId = jsonObject.getInteger("userId");
            String nickName = jsonObject.getString("nickName");

            String avatarUrl = jsonObject.getString("avatarUrl");
            String openid = jsonObject.getString("openid");
            String unionId = jsonObject.getString("unionId");

            Assert.hasText(openid, "openid不能为空");
            Assert.hasText(unionId, "unionId不能为空");

            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("openid", openid);
            User user = userMapper.selectOne(userQueryWrapper);
            if (nickName!=null) {
                user.setNickName(nickName);
            }
            if (avatarUrl!=null){
                user.setAvatarUrl(avatarUrl);
            }

            return Result.ok(user);
        } catch (Exception e) {
            log.error(e.toString());
            return Result.error("系统异常");
        }
    }
//
//    @Autowired
//    private TokenProvider tokenProvider;
//    @Autowired
//    private RedisTemplate<String, TokenUser> tokenRedisTemplate;
//
//    /**
//     * 通过code获取openid
//     */
////    @IgnoreAppToken
//    @ApiOperation("通过 openid 登录")
//    @GetMapping("/getUserByopenid")
//    public Result getUserByopenid(HttpServletResponse response,String openId) {
//        try {
//            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//            userQueryWrapper.eq("openid",openId);
//            User user = userMapper.selectOne(userQueryWrapper);
//
//            if (ObjectUtil.isNull(user)){
//                return Result.error("无用户,请授权登录");
//            }
//
//            if (ObjectUtil.isNull(user.getTelphone())){
//                return Result.error("请授权手机号");
//            }
//
//            // token处理
//            TokenUser token = new TokenUser();
//            // token构建
//            String tokenId = StringTool.get36UUID();
//            token.setTokenId(tokenId);
//            token.setUserId(String.valueOf(user.getId()));
//            token.setOpenId(openId);
//            token.setIsWx(true);
//            token.setTelphone(user.getTelphone());
//            token.setNickName(user.getNickName());
//            token.setAvatarUrl(user.getAvatarUrl());
//
//
//            String responseToken = tokenProvider.buildToken(token);
//            log.info("##############" + responseToken);
//            TokenService.getPublicParameter().setToken(responseToken);
//            // 添加token有效期到redis
//            response.setHeader("Access-Control-Expose-Headers", TokenConsts.AUTHORIZATION_HEADER);
//            response.setHeader(TokenConsts.AUTHORIZATION_HEADER, responseToken);
//            addTokenExpireToRedis(token.getUserId(), tokenId);
//            // 登录成功返回
//            //更新登录时间
//            user.setUpdateTime(new Date());
//            user.updateById();
//
//            return Result.ok(user);
//        } catch (Exception e) {
//            log.error(e.toString());
//            return Result.error("系统异常");
//        }
//    }

//    /**
//     * 储存token
//     *
//     * @param userId
//     * @param tokenId
//     */
//    private void addTokenExpireToRedis(String userId, String tokenId) {
//        String loginKey = RedisKey.getTokenExpireKey(userId);
//        // 2小时(毫秒)后过期, 小时内操作会续航
//        long expireTime = System.currentTimeMillis() + TimeInterval.MILLISECOND_PER_HOUR * 6;
//        //log.info("userIdKey:{},tokenId:{}", loginKey, tokenId);
//        tokenRedisTemplate.opsForHash().put(loginKey, tokenId, String.valueOf(expireTime));
//        //log.info("expireTime:{}", tokenRedisTemplate.opsForHash().get(loginKey, tokenId));
//    }

}
